package com.study.io.nio.demo.buffer;

import com.study.common.utils.RamUtil;

import java.nio.ByteBuffer;

/**
 * 堆外内存 demo
 * <p>
 * 所分配的内存不在 JVM 堆上, 不受 GC 的管理.(但是 Direct Buffer 的 Java 对象是由 GC 管理的, 因此当发生 GC, 对象被回收时, Direct Buffer 也会被释放)
 * 因为 Direct Buffer 不在 JVM 堆上分配, 因此 Direct Buffer 对应用程序的内存占用的影响就不那么明显(实际上还是占用了这么多内存, 但是 JVM 不好统计到非 JVM 管理的内存)
 * 申请和释放 Direct Buffer 的开销比较大. 因此正确的使用 Direct Buffer 的方式是在初始化时申请一个 Buffer, 然后不断复用此 buffer, 在程序结束后才释放此 buffer
 * 使用 Direct Buffer 时, 当进行一些底层的系统 IO 操作时, 效率会比较高, 因为此时 JVM 不需要拷贝 buffer 中的内存到中间临时缓冲区中
 * <p>
 * 堆外内存缓冲
 * （1）在使用 DirectByteBuffer 堆外内存中 必须允许手动gc 否则容易出现oom
 * （2）默认大小与堆内存一致
 * （3）建议使用过程中单独设置堆外内存 -XX:MaxDirectMemorySize=1024M
 * （4）java中使用堆外内存  进程内空间=用户空间
 * （5）申请慢
 *
 * @author wuxj
 */
public class DirectByteBufferDemo {

    public static void main(String[] args) {
        //打印内存日志
        RamUtil.getRam();
        ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024 * 127);
        //打印内存日志
        RamUtil.getRam();

        //写入内存数据
        directBuffer.put("你好".getBytes());

        //读取数据
        //将post移动到初始位置  为了读取数据
        directBuffer.flip();
        byte[] b = new byte[6];
        directBuffer.get(b);
        System.out.println(new String(b));

        //清除缓存
        //directBuffer.clear();

        while (true) {
            try {
                Thread.sleep(1000);

                ByteBuffer.allocateDirect(1024 * 200);
                RamUtil.getRam();
            } catch (Exception e) {

            }
        }
    }
}
